﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace ICodeShare.UI.Controls
{
    /// <summary>
    /// 水印显示方式
    /// </summary>
    public enum WordNumberMode
    {
        /// <summary>
        /// 当文本框为空时就显示水印，不管该文本框有没有获得焦点
        /// </summary>
        Always,
        /// <summary>
        /// 当文本框失去焦点且文本框没有内容时显示水印
        /// </summary>
        Focused,
    }

    public class WordNumberAdorner : Adorner
    {
        #region Members

        private TextBox adornedTextBox;
        private VisualCollection _visuals;
        private TextBlock textBlock;
        private WordNumberMode showMode;
        private int _txtMaxLength = 255;
        private const double MINWIDTH = 40;

        #endregion

        #region Constructors

        public WordNumberAdorner(UIElement adornedElement)
            : base(adornedElement)
        {
            if (adornedElement is TextBox)
            {
                adornedTextBox = adornedElement as TextBox;
                adornedTextBox.TextChanged += (s1, e1) =>
                {
                    this.SetWordNumberVisible(true,adornedTextBox.Text.Length);
                };
                adornedTextBox.GotFocus += (s1, e1) =>
                {
                    this.SetWordNumberVisible(true);
                };
                adornedTextBox.LostFocus += (s1, e1) =>
                {
                    this.SetWordNumberVisible(false);
                };

                this._txtMaxLength = (adornedTextBox.MaxLength != 0) ? adornedTextBox.MaxLength : 255;

                _visuals = new VisualCollection(this);

                textBlock = new TextBlock()
                {
                    HorizontalAlignment =HorizontalAlignment.Right,
                    VerticalAlignment = VerticalAlignment.Bottom,
                    FontSize=9,
                    MinWidth=MINWIDTH,
                    Text = string.Format("{0}/{1}", adornedTextBox.Text.Length, _txtMaxLength),
                    Foreground = WordNumberAdorner.GetForeground(adornedElement),
                    Padding=new Thickness(5,0,0,0),
                    Margin=new Thickness(0,0,-MINWIDTH,adornedTextBox.BorderThickness.Bottom),
                };
                _visuals.Add(textBlock);

                this.showMode = WordNumberAdorner.GetWordNumberShowMode(adornedElement);
               
            }
            this.IsHitTestVisible = false;
        }

        #endregion

        #region Dependency Property

        #region ShowWordNumber 是否显示字符个数

        public static bool GetShowWordNumber(DependencyObject obj)
        {
            return (bool)obj.GetValue(ShowWordNumberProperty);
        }

        public static void SetShowWordNumber(DependencyObject obj, bool value)
        {
            obj.SetValue(ShowWordNumberProperty, value);
        }

        private static readonly DependencyProperty ShowWordNumberProperty = DependencyProperty.RegisterAttached(
            "ShowWordNumber",
            typeof(bool),
            typeof(WordNumberAdorner),
            new PropertyMetadata(false, OnShowWordNumberChangedCallBack));

        private static void OnShowWordNumberChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if ((bool)e.NewValue)
            {
                if (element != null)
                {
                    var adornerLayer = AdornerLayer.GetAdornerLayer(element);

                    if (adornerLayer != null)
                    {
                        adornerLayer.Add(new WordNumberAdorner(element as UIElement));
                    }
                    else
                    {
                        //layer为null，说明还未load过（整个可视化树中没有装饰层的情况不考虑）
                        //在控件的loaded事件内生成装饰件
                        element.Loaded += (s1, e1) =>
                        {
                            var adorner = new WordNumberAdorner(element);
                            var ad = AdornerLayer.GetAdornerLayer(element);
                            if (ad != null)
                            {
                                ad.Add(adorner);
                            }
                            //AdornerLayer.GetAdornerLayer(element).Add(adorner);
                        };
                    }
                }
            }
        }

        #endregion

        #region Foreground 字体颜色

        /// <summary>
        /// Gets the brush used to draw the mouse over font color.
        /// </summary>
        public static Brush GetForeground(DependencyObject element)
        {
            return (Brush)element.GetValue(ForegroundProperty);
        }

        /// <summary>
        /// Sets the brush used to draw the mouse over font color.
        /// </summary>
        public static void SetForeground(DependencyObject element, Brush value)
        {
            element.SetValue(ForegroundProperty, value);
        }

        /// <summary>
        /// DependencyProperty for <see cref="Foreground" /> property.
        /// </summary>
        public static readonly DependencyProperty ForegroundProperty = DependencyProperty.RegisterAttached(
            "Foreground",
            typeof(Brush),
            typeof(WordNumberAdorner),
            new FrameworkPropertyMetadata(Brushes.Black));

        #endregion Foreground 字体颜色

        #region LostFocusedOpacity 水印透明度

        public static double GetLostFocusedOpacity(DependencyObject obj)
        {
            return (double)obj.GetValue(LostFocusedOpacityProperty);
        }

        public static void SetLostFocusedOpacity(DependencyObject obj, double value)
        {
            obj.SetValue(LostFocusedOpacityProperty, value);
        }

        public static readonly DependencyProperty LostFocusedOpacityProperty = DependencyProperty.RegisterAttached(
            "LostFocusedOpacity",
            typeof(double),
            typeof(WordNumberAdorner),
            new PropertyMetadata(0.56));
        #endregion

        #region WordNumberShowMode

        public static WordNumberMode GetWordNumberShowMode(DependencyObject obj)
        {
            return (WordNumberMode)obj.GetValue(WordNumberShowModeProperty);
        }

        public static void SetWordNumberShowMode(DependencyObject obj, WordNumberMode value)
        {
            obj.SetValue(WordNumberShowModeProperty, value);
        }

        public static readonly DependencyProperty WordNumberShowModeProperty = DependencyProperty.RegisterAttached(
            "WordNumberShowMode",
            typeof(WordNumberMode),
            typeof(WordNumberAdorner),
            new PropertyMetadata(WordNumberMode.Always));

        #endregion

        #endregion

        protected override int VisualChildrenCount
        {
            get
            {
                return _visuals.Count;
            }
        }

        protected override Visual GetVisualChild(int index)
        {
            return _visuals[index];
        }

        protected override Size MeasureOverride(Size constraint)
        {
            return base.MeasureOverride(constraint);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            textBlock.Arrange(new Rect(finalSize));

            return base.ArrangeOverride(finalSize);
        }

        private string BuildWordNumber(int length,int maxLength)
        {
            return string.Format("{0}/{1}",length,maxLength);
        }

        private void SetWordNumberVisible(bool isFocus,int length=0)
        {
            
            this.textBlock.Text = BuildWordNumber(length, _txtMaxLength);
            switch (this.showMode)
            {
                case WordNumberMode.Always:
                    {
                        if (!isFocus)
                        {
                            this.textBlock.Opacity = GetLostFocusedOpacity(this);
                        }
                        else
                        {
                            this.textBlock.Opacity = 1.0;
                        }
                        break;
                    }
                case WordNumberMode.Focused:
                    {
                        if (isFocus)
                        {
                            this.textBlock.Visibility = Visibility.Visible;
                        }
                        else
                        {
                            this.textBlock.Visibility = Visibility.Collapsed;
                        }
                        break;
                    }
                default:
                    break;
            }
        }
    }
}
